# -*- coding: utf-8 -*-
# @Time    : 2018/5/24 下午10:38
# @Author  : Lavn
# @Email   : 959875529@qq.com
# @File    : iterator.py
# @Software: PyCharm

#比如在 Java 中，我们通过 List 集合的下标来遍历 List 集合中的元素，在 Python 中，给定一个 list 或 tuple
#我们可以通过 for 循环来遍历这个 list 或 tuple ，这种遍历就是迭代。

# 可是，Python 的 for 循环抽象程度要高于 Java 的 for 循环的，为什么这么说呢？因为 Python 的 for
#  循环不仅可以用在 list 或tuple 上，
# 还可以作用在其他可迭代对象上。也就是说，只要是可迭代的对象，无论有没有下标，都是可以迭代的。

# 1、for 循环迭代字符串
for char in 'liangdianshui' :
    print ( char , end = ' ' )
print('\n')

# 2、for 循环迭代 list
list1 = [1,2,3,4,5]
for num1 in list1 :
    print ( num1 , end = ' ' )

print('\n')
# 3、for 循环也可以迭代 dict （字典）
dict1 = {'name':'两点水','age':'23','sex':'男'}

for key in dict1 :    # 迭代 dict 中的 key
    print ( key , end = ' ' )

print('\n')

for value in dict1.values() :   # 迭代 dict 中的 value
	print ( value , end = ' ' )

print ('\n')

# 如果 list 里面一个元素有两个变量，也是很容易迭代的
for x , y in [ (1,'a') , (2,'b') , (3,'c') ] :
	print ( x , y )
print ('\n')

#迭代器
# 1、字符创创建迭代器对象
str1 = 'liangdianshui'
iter1 = iter ( str1 )

# 2、list对象创建迭代器
list1 = [1,2,3,4]
iter2 = iter ( list1 )

# 3、tuple(元祖) 对象创建迭代器
tuple1 = ( 1,2,3,4 )
iter3 = iter ( tuple1 )

# for 循环遍历迭代器对象
for x in iter1:
    print ( x , end = ' ' )

print ('\n')
# next() 函数遍历迭代器
while True :
    try :
        print ( next ( iter3 ) )
    except StopIteration :
        break
print('\n')

#list 生成式
list1=list ( range (1,31) )
print(list1)
print('\n')

#乘法表
# print('\n'.join([' '.join ('%dx%d=%2d' % (x,y,x*y)  for x in range(1,y+1)) for y in range(1,10)]))

#[expr for iter_var in iterable]
#[expr for iter_var in iterable if cond_expr]
lsit1=[x * x for x in range(1, 11)]
print(lsit1)
print('\n')

lsit1= [x * x for x in range(1, 11) if x % 2 == 0]
print(lsit1)
print('\n')


# -*- coding: UTF-8 -*-
lsit1= [(x+1,y+1) for x in range(3) for y in range(5)]
print(lsit1)
print('\n')


#生成器
#通过上面的学习，可以知道列表生成式，我们可以直接创建一个列表。但是，受到内存限制，列表容量肯定是有限的。而且，创建一个包含 1000 万个元素的列表，
#不仅占用很大的存储空间，如果我们仅仅需要访问前面几个元素，那后面绝大多数元素占用的空间都白白浪费了。
#所以，如果列表元素可以按照某种算法推算出来，那我们是否可以在循环的过程中不断推算出后续的元素呢？这样就不必创建完整的 list，从而节省大量的空间。
#在 Python 中，这种一边循环一边计算的机制，称为生成器：generator。
#在 Python 中，使用了 yield 的函数被称为生成器（generator）。
#跟普通函数不同的是，生成器是一个返回迭代器的函数，只能用于迭代操作，更简单点理解生成器就是一个迭代器。
#在调用生成器运行的过程中，每次遇到 yield 时函数会暂停并保存当前所有的运行信息，返回yield的值。并在下一次执行 next()方法时从当前位置继续运行。
#那么如何创建一个生成器呢？

#最简单最简单的方法就是把一个列表生成式的 [] 改成 ()
gen= (x * x for x in range(10))
print(gen)

# for num  in  gen :
# 	print(num)

while True:
    try:
        print(next(gen))
    except StopIteration:
        break
print('\n')

#以函数的形式实现生成器
# def my_function():
#     for i in range(10):
#         print ( i )
#
# my_function()

#如果我们需要把它变成生成器，我们只需要把 print ( i ) 改为 yield i 就可以了，具体看下修改后的例子：
def my_function():
    for i in range(10):
        yield i

print(my_function())
print('\n')


# -*- coding: UTF-8 -*-
def odd():
    print ( 'step 1' )
    yield ( 1 )
    print ( 'step 2' )
    yield ( 3 )
    print ( 'step 3' )
    yield ( 5 )

o = odd()
print(o)
print('\n')


def triangles( n ):         # 杨辉三角形
    L = [1]
    while True:
        yield L
        L.append(0)
        print(L)
        L = [ L [ i -1 ] + L [ i ] for i in range (len(L))]
        print(L)


n= 0
for t in triangles( 10 ):   # 直接修改函数名即可运行
    print(t)
    n = n + 1
    if n == 10:
        break